import os
from jinja2 import Environment
from dataclasses import asdict
from typing import Dict, List, Any
from miaoma.models.react_meta_info import ReactTableMetaInfo, map_sql_to_typescript_type
from src.base import bera
from src.base import camel_case_filter
import random
import faker

# 入口函数，用于生成所有 React 相关代码
def generate_react_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str = 'artifacts/miaoma/react'):
    # 测试项目根目录
    test_project_folder = 'artifacts/miaoma/react'

    # 真实项目根目录
    real_project_folder = os.path.join(bera.get_variable("home_directory"), "workspace/bera/beracode/learn-ui-react")

    # Java 源码文件夹路径
    project_root_dir = real_project_folder

    os.makedirs(project_root_dir, exist_ok=True)

    generate_react_interface_code(table_meta, templates, project_root_dir)    # 生成 React 接口文件
    generate_react_table_code(table_meta, templates, project_root_dir)        # 生成 React 表格组件文件
    generate_react_mock_data_code(table_meta, templates, project_root_dir)    # 生成 Mock 数据文件
    generate_react_api_code(table_meta, templates, project_root_dir)          # 生成 API 请求文件
    generate_react_list_page_code(table_meta, templates, project_root_dir)    # 生成 ListPage 文件代码
    generate_react_detail_page_code(table_meta, templates, project_root_dir)  # 生成详情页面代码
    generate_react_add_or_edit_modal_code(table_meta, templates, project_root_dir)        # 生成模态框代码
    generate_react_route_code(table_meta, templates, project_root_dir)        # 生成路由文件代码

# 生成 React 接口文件代码
def generate_react_interface_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染接口模板
    interface_code = templates.get_template('react/react_model.j2').render(table_info_dict)
    interface_file_name = f"{table_meta.class_name}.ts"
    interface_path = os.path.join(output_folder, interface_file_name)

    # 写入接口文件
    with open(interface_path, 'w') as f:
        f.write(interface_code)
    bera.logger.info(f"Generated React interface code for {table_meta.class_name} at {interface_path}")

# 生成 React 列表页面代码
def generate_react_list_page_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染列表页面模板
    list_page_code = templates.get_template('react/react_list_page.j2').render(table_info_dict)
    list_page_file_name = f"{table_meta.class_name}ListPage.tsx"
    list_page_path = os.path.join(output_folder, list_page_file_name)

    # 写入列表页面文件
    with open(list_page_path, 'w') as f:
        f.write(list_page_code)
    bera.logger.info(f"Generated React list page code for {table_meta.class_name} at {list_page_path}")

# 生成 React 表格组件代码
def generate_react_table_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染表格组件模板
    table_code = templates.get_template('react/react_columns.j2').render(table_info_dict)
    table_file_name = f"tableColumns{table_meta.class_name}.tsx"
    table_path = os.path.join(output_folder, table_file_name)

    # 写入表格组件文件
    with open(table_path, 'w') as f:
        f.write(table_code)
    bera.logger.info(f"Generated React table component code for {table_meta.class_name} at {table_path}")

# 生成 Mock 数据文件代码
def generate_react_mock_data_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 生成初始数据列表
    initial_data = generate_mock_data_list(table_meta)

    # 将 table_meta 和初始数据列表转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)
    table_info_dict['initial_data'] = initial_data

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染 Mock 数据模板
    mock_filename = 'react/react_mock_data2.j2'
    mock_data_code = templates.get_template(mock_filename).render(table_info_dict)
    mock_data_file_name = f"mock{table_meta.class_name}Data.ts"
    mock_data_path = os.path.join(output_folder, mock_data_file_name)

    # 写入 Mock 数据文件
    with open(mock_data_path, 'w') as f:
        f.write(mock_data_code)
    bera.logger.info(f"Generated React mock data code for {table_meta.class_name} at {mock_data_path}")

# 生成 Mock 数据列表
def generate_mock_data_list(table_meta: ReactTableMetaInfo, count: int = 5) -> List[Dict[str, Any]]:
    mock_data_list = []
    fake = faker.Faker()  # 使用 faker 生成随机数据

    for _ in range(count):
        record = []
        for column in table_meta.columns:
            field_name = camel_case_filter(column.sql_raw_info.name)
            field_type = column.sql_raw_info.type.upper()
            typescript_type = map_sql_to_typescript_type(field_type)

            # 根据字段类型生成随机数据
            if 'INT' in field_type:
                field_value = random.randint(1, 100)
            elif 'VARCHAR' in field_type or 'TEXT' in field_type:
                field_value = fake.text(max_nb_chars=20)
            elif 'DATE' in field_type or 'TIME' in field_type:
                field_value = fake.iso8601()
            elif 'DECIMAL' in field_type or 'FLOAT' in field_type or 'DOUBLE' in field_type:
                field_value = round(random.uniform(10.0, 100.0), 2)
            elif 'BOOLEAN' in field_type or 'BIT' in field_type:
                field_value = random.choice([True, False])
            else:
                field_value = None  # 其他类型暂时填充为 None

            # 将字段的所有信息存入 record 列表中
            record.append({
                "field_name": field_name,
                "field_value": field_value,
                "typescript_type": typescript_type
            })

        mock_data_list.append(record)

    return mock_data_list

# 生成 React API 请求代码
def generate_react_api_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染 API 请求模板
    api_code = templates.get_template('react/react_api.j2').render(table_info_dict)
    api_file_name = f"api{table_meta.class_name}.ts"
    api_path = os.path.join(output_folder, api_file_name)

    # 写入 API 请求文件
    with open(api_path, 'w') as f:
        f.write(api_code)
    bera.logger.info(f"Generated React API request code for {table_meta.class_name} at {api_path}")

# 生成 React 模态框组件代码
def generate_react_add_or_edit_modal_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染模态框组件模板
    modal_code = templates.get_template('react/react_add_or_edit_modal.j2').render(table_info_dict)
    modal_file_name = f"{table_meta.class_name}AddOrEditModal.tsx"
    modal_path = os.path.join(output_folder, modal_file_name)

    # 写入模态框组件文件
    with open(modal_path, 'w') as f:
        f.write(modal_code)
    bera.logger.info(f"Generated React modal component code for {table_meta.class_name} at {modal_path}")

# 生成 React 详情页面代码
def generate_react_detail_page_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/logic/auto/{table_meta.entity_name}')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染详情页面模板
    detail_page_code = templates.get_template('react/react_detail_page.j2').render(table_info_dict)
    detail_page_file_name = f"{table_meta.class_name}DetailPage.tsx"
    detail_page_path = os.path.join(output_folder, detail_page_file_name)

    # 写入详情页面文件
    with open(detail_page_path, 'w') as f:
        f.write(detail_page_code)
    bera.logger.info(f"Generated React detail page code for {table_meta.class_name} at {detail_page_path}")

# 生成 React 路由代码
def generate_react_route_code(table_meta: ReactTableMetaInfo, templates: Environment, project_root_dir: str):
    # 将 table_info 转换为字典形式，便于模板渲染
    table_info_dict = asdict(table_meta)

    output_folder = os.path.join(project_root_dir, f'src/route/auto')
    os.makedirs(output_folder, exist_ok=True)

    # 渲染路由模板
    route_code = templates.get_template('react/react_route.j2').render(table_info_dict)
    route_file_name = f"route{table_meta.class_name}.tsx"
    route_path = os.path.join(output_folder, route_file_name)

    # 写入路由文件
    with open(route_path, 'w') as f:
        f.write(route_code)
    bera.logger.info(f"Generated React route code for {table_meta.class_name} at {route_path}")
